﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.IO;

namespace GeradorMassaDados.Bovespa.Business
{
    public class SQLCommandLog
    {
        #region Fields

        private string sqlFormated;
        const char parameterStartMarck = 'þ';
        const char parameterEndMarck = '¬';

        #endregion

        #region properties

        /// <summary>
        /// Sql do campo do campo sem os valores dos paramêtros
        /// </summary>
        public string SQLText { get; internal set; }

        /// <summary>
        /// Os valores dos campos com a seguinte notação
        /// # determina o começo do campo
        /// (N) o número de caracteres após que o campo ocupa
        /// : o valor do campo guardado
        /// </summary>
        public string SQLBind { get; internal set; }

        /// <summary>
        /// Número da linha retornada para essa consulta 
        /// </summary>
        public int RowNumber { get; internal set; }

        /// <summary>
        /// Campo com a comando formatado
        /// </summary>
        public string SQLFormated
        {
            get
            {
                if (null == sqlFormated)
                    FormatSQLCommand();
                return sqlFormated;
            }
        }

        public DateTime Extend { get; set; }

        #endregion

        #region Methods

        /// <summary>
        /// Formata o campo SQLFormated para a apresentação 
        /// </summary>
        void FormatSQLCommand()
        {
            sqlFormated = string.Empty;

            // A matriz começa com # entao gera o primeiro item vazio
            var bindArray = SQLBind.Split('#');
            if (bindArray.Length > 1)
            {
                var auxArray = new string[bindArray.Length - 1];
                Array.Copy(bindArray, 1, auxArray, 0, auxArray.Length);
                bindArray = auxArray;
            }

            string[] paramNames;
            sqlFormated = StampParameter(this.SQLText, out paramNames);

            for (int i = 0; i < Math.Min(bindArray.Length, paramNames.Length); i++)
            {
                string bind = bindArray[i];
                if (string.IsNullOrEmpty(bind)) continue;

                var paramLength = GetParamLength(bind);

                string paramValue = string.Concat(
                    "'",
                    FormatToPortuguese(bind.Substring(bind.IndexOf(':') + 1, paramLength)),
                    "'");

                sqlFormated = sqlFormated.Replace(
                    paramNames[i],
                    paramValue);
            }
            sqlFormated = sqlFormated.Replace(parameterStartMarck, ':').Replace(new string(parameterEndMarck, 1), "");
        }

        /// <summary>
        /// Carimba cada parametro com uma dentro de uma marcação inicial 'þ' e final '¬'
        /// </summary>
        /// <param name="sqlText"></param>
        /// <param name="paramNames"></param>
        /// <returns></returns>
        string StampParameter(string sqlText, out string[] paramNames)
        {
            var listParamNames = new List<string>();
            sqlText = sqlText.Replace(':', parameterStartMarck);

            int i = 0;
            while ((i = sqlText.IndexOf(parameterStartMarck, i)) < sqlText.Length && i >= 0)
            {
                for (int j = i; j < sqlText.Length; j++)
                    if (('_' != sqlText[j] && !char.IsLetterOrDigit(sqlText, j)) || j == sqlText.Length - 1)
                    {
                        sqlText = sqlText.Insert(j, "" + parameterEndMarck);
                        listParamNames.Add(sqlText.Substring(i, j - i + 1));
                        i = j + 1;
                        break;
                    }
            }
            paramNames = listParamNames.ToArray();
            return sqlText;
        }

        /// <summary>
        /// Faz as mudanças para exibir em portugues [por enquanto só data]
        /// </summary>
        /// <param name="paramValue"></param>
        /// <returns></returns>
        string FormatToPortuguese(string paramValue)
        {
            int dateSlash1, dateSlash2;

            dateSlash1 = paramValue.IndexOf('/');
            if (dateSlash1 > 0)
            {
                dateSlash2 = paramValue.IndexOf('/', dateSlash1 + 1);
                if (dateSlash2 > 0)
                {
                    string[] date = paramValue.Split('/');
                    string aux;

                    aux = date[0];
                    date[0] = date[1];
                    date[1] = aux;

                    paramValue = string.Join("/", date);
                }
            }
            return paramValue;
        }

        /// <summary>
        /// Obtém o tamanho do paramêtro
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns>Tamanho do parametro</returns>
        int GetParamLength(string parameter)
        {
            var startIndex = parameter.IndexOf("(");
            var endIndex = parameter.IndexOf(")");

            return int.Parse(parameter.Substring(startIndex + 1, endIndex - startIndex - 1));
        }

        #endregion
    }
}